home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-08-25 | 5.7 KB | 182 lines | [TEXT/PJMM] |
-
- { ################################################################### }
- { ## ## }
- { ## ## ##### ##### ## ## ## ## ## ## ## ## ## }
- { ## ## ### ## ## ## # ## ### ## ## ## ## ## ## }
- { ## ## ### ##### ####### ## ## #### ###### ## }
- { ## ## ### ## ## ### ### ## ## ## ## ## ## ## }
- { ## ##### ##### ## ## ## ## #### ## ## ## ## ## ## }
- { ## ## }
- { ## EXTREMELY FAST AND EASY TO UNDERSTAND COMPRESSION ALGORITM ## }
- { ## ## }
- { ################################################################### }
- { ## ## }
- { ## This unit implements the updated LZRW1/KH algoritm which ## }
- { ## also implements some RLE coding which is usefull when ## }
- { ## compress files containing a lot of consecutive bytes ## }
- { ## having the same value. The algoritm is not as good as ## }
- { ## LZH, but can compete with Lempel-Ziff. It's the fasted ## }
- { ## one I've encountered upto now. ## }
- { ## ## }
- { ## ## }
- { ## ## }
- { ## Kurt HAENEN ## }
- { ## ## }
- { ################################################################### }
-
- unit LZRW1KH;
-
- interface
-
- const
- BufferMaxSize = 32768;
- BufferMax = BufferMaxSize - 1;
- FLAG_Copied = $80;
- FLAG_Compress = $40;
-
- type
- BufferIndex = 0..BufferMax;
- BufferSize = 0..BufferMaxSize;
- BufferArray = packed array[BufferIndex] of BYTE;
- BufferPtr = ^BufferArray;
-
- function LZRW1KHCompress (Source, Dest: BufferPtr; SourceSize: BufferSize): BufferSize;
- function LZRW1KHDecompress (Source, Dest: BufferPtr; SourceSize: BufferSize): BufferSize;
-
- implementation
-
- type
- HashTable = array[0..4095] of INTEGER;
- WORD = longInt;
-
- function LZRW1KHCompress (Source, Dest: BufferPtr; SourceSize: BufferSize): BufferSize;
- var
- Hash: HashTable;
-
- function GetMatch (X: BufferIndex; var Size: WORD; var Pos: BufferIndex): BOOLEAN;
- var
- HashValue: WORD;
- begin
- HashValue := BAND(BSR(40543 * BXOR(BSL(BXOR(BSL(Source^[X], 4), Source^[X + 1]), 4), Source^[X + 2]), 4), $0FFF);
-
- GetMatch := FALSE;
- if (Hash[HashValue] <> -1) and (X - Hash[HashValue] < 4096) then begin
- Pos := Hash[HashValue];
- Size := 0;
- while ((Size < 18) & (Source^[X + Size] = Source^[Pos + Size]) & (X + Size < SourceSize)) do
- Size := Size + 1;
- GetMatch := (Size >= 3)
- end;
- Hash[HashValue] := X
- end;
-
- var
- Key, Bit, Command, Size: WORD;
- X, Y, Z, Pos: BufferIndex;
- begin
- for Key := 0 to 4095 do
- Hash[Key] := -1;
- Dest^[0] := FLAG_Compress;
- X := 0;
- Y := 3;
- Z := 1;
- Bit := 0;
- Command := 0;
- while (X < SourceSize) & (Y <= SourceSize) do begin
- if (Bit > 15) then begin
- Dest^[Z] := BAND(BSR(Command, 8), $FF);
- Dest^[Z + 1] := BAND(Command, $FF);
- Z := Y;
- Bit := 0;
- Y := Y + 2;
- end;
- Size := 1;
- while ((Source^[X] = Source^[X + Size]) & (Size < $FFF) & (X + Size < SourceSize)) do
- Size := Size + 1;
- if (Size >= 16) then begin
- Dest^[Y] := 0;
- Dest^[Y + 1] := BAND(BSR(Size - 16, 8), $FF);
- Dest^[Y + 2] := BAND(Size - 16, $FF);
- Dest^[Y + 3] := Source^[X];
- Y := Y + 4;
- X := X + Size;
- Command := BSL(Command, 1) + 1;
- end
- else if (GetMatch(X, Size, Pos)) then begin
- Key := BSL(X - Pos, 4) + (Size - 3);
- Dest^[Y] := BAND(BSR(Key, 8), $FF);
- Dest^[Y + 1] := BAND(Key, $FF);
- Y := Y + 2;
- X := X + Size;
- Command := BSL(Command, 1) + 1;
- end
- else begin
- Dest^[Y] := Source^[X];
- Y := Y + 1;
- X := X + 1;
- Command := BSL(Command, 1);
- end;
- Bit := Bit + 1;
- end;
- Command := BSL(Command, 16 - Bit);
- Dest^[Z] := BAND(BSR(Command, 8), $FF);
- Dest^[Z + 1] := BAND(Command, $FF);
- if (Y > SourceSize) then begin
- BlockMove(@Source^[0], @Dest^[1], SourceSize);
- Dest^[0] := FLAG_Copied;
- Y := SourceSize + 1;
- end;
- LZRW1KHCompress := Y
- end;
-
- function LZRW1KHDecompress (Source, Dest: BufferPtr; SourceSize: BufferSize): BufferSize;
- var
- X, Y, Pos: BufferIndex;
- Command, Size, K: WORD;
- Bit: BYTE;
- begin
- if (Source^[0] = FLAG_Copied) then begin
- BlockMove(@Source^[1], @Dest^[0], SourceSize - 1);
- Y := SourceSize - 1;
- end
- else begin
- Y := 0;
- X := 3;
- Command := BSL(Source^[1], 8) + Source^[2];
- Bit := 16;
- while (X < SourceSize) do begin
- if (Bit = 0) then begin
- Command := BSL(Source^[X], 8) + Source^[X + 1];
- Bit := 16;
- X := X + 2;
- end;
- if (BAND(Command, $8000) = 0) then begin
- Dest^[Y] := Source^[X];
- Y := Y + 1;
- X := X + 1;
- end
- else begin
- Pos := BSL(Source^[X], 4) + BSR(Source^[X + 1], 4);
- if (Pos = 0) then begin
- Size := BSL(Source^[X + 1], 8) + Source^[X + 2] + 15;
- for K := 0 to Size do
- Dest^[Y + K] := Source^[X + 3];
- X := X + 4;
- Y := Y + Size + 1;
- end
- else begin
- Size := BAND(Source^[X + 1], $0F) + 2;
- for K := 0 to Size do
- Dest^[Y + K] := Dest^[Y - Pos + K];
- X := X + 2;
- Y := Y + Size + 1;
- end;
- end;
- Command := BSL(Command, 1);
- Bit := Bit - 1;
- end
- end;
- LZRW1KHDecompress := Y
- end;
-
- end.